#include <sys/time.h>
#include <stdio.h>
#include <lvgl.h>
#include "lv_conf.h"
#include <sdl/sdl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define DISP_BUF_SIZE 800 * 480 * 2

void init_input_output()
{
    // 初始化显示sdl
    sdl_init();
    // 输出接口
    static lv_color_t buf[DISP_BUF_SIZE];  // 显示缓冲区
    static lv_color_t buf1[DISP_BUF_SIZE]; // 显示缓冲区
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, buf1, DISP_BUF_SIZE);
    // 设置显示缓冲区属性
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &disp_buf;
    disp_drv.flush_cb = sdl_display_flush;
    disp_drv.hor_res = 800;
    disp_drv.ver_res = 480;
    lv_disp_drv_register(&disp_drv);

    // 输入接口
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1);          /*Basic initialization*/
    indev_drv_1.type = LV_INDEV_TYPE_POINTER; // 设置输入事件类型
    indev_drv_1.read_cb = sdl_mouse_read;
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);
}

// 全局变量
static lv_obj_t *display;            // 显示区域对象
static char current_input[32] = {0}; // 当前输入的数字字符串
static double current_value = 0;     // 当前计算值
static double previous_value = 0;    // 上一个计算值
static char last_operator = 0;       // 上一个操作符

// 按钮点击事件回调函数
static void btn_event_cb(lv_event_t *e)
{
    lv_obj_t *btn = lv_event_get_target(e);     // 获取触发事件的按钮对象
    lv_obj_t *label = lv_obj_get_child(btn, 0); // 获取按钮上的标签对象
    const char *txt = lv_label_get_text(label); // 获取标签的文本内容

    if (strchr("0123456789.", *txt)) // 如果是数字或小数点
    {
        if (strcmp(current_input, "0") == 0 && *txt != '.') // 如果当前输入是"0"且不是小数点
        {
            strcpy(current_input, txt); // 替换为新的数字
        }
        else if (strlen(current_input) < sizeof(current_input) - 1) // 如果当前输入长度未达到最大限制
        {
            if (!(strchr(current_input, '.') && *txt == '.')) // 如果没有重复的小数点
            {
                strcat(current_input, txt); // 追加新字符
            }
        }
        lv_textarea_set_text(display, current_input); // 更新显示区域
    }
    else if (strchr("+-X/", *txt)) // 如果是操作符
    {
        if (last_operator) // 如果已经有上一个操作符
        {
            switch (last_operator) // 根据上一个操作符进行计算
            {
            case '+':
                current_value += atof(current_input); // 加法
                break;
            case '-':
                current_value -= atof(current_input); // 减法
                break;
            case 'X':
                current_value *= atof(current_input); // 乘法
                break;
            case '/':
                if (atof(current_input) != 0)
                {
                    current_value /= atof(current_input); // 除法
                }
                else
                {
                    lv_textarea_set_text(display, "Error");
                    return;
                }
                break;
            }
        }
        else // 如果没有上一个操作符
        {
            current_value = atof(current_input); // 将当前输入转换为数值
        }

        last_operator = *txt;    // 更新上一个操作符
        current_input[0] = '\0'; // 清空当前输入
        char buf[32];
        snprintf(buf, sizeof(buf), "%.6g", current_value); // 格式化当前值
        lv_textarea_set_text(display, buf);                // 更新显示区域
    }
    else if (*txt == 'C') // 如果是清除键
    {
        current_input[0] = '\0';            // 清空当前输入
        current_value = 0;                  // 重置当前值
        last_operator = 0;                  // 清除上一个操作符
        lv_textarea_set_text(display, "0"); // 更新显示区域为"0"
    }
    else if (*txt == '=') // 如果是等于键
    {
        if (last_operator) // 如果已经有上一个操作符
        {
            switch (last_operator) // 根据上一个操作符进行最终计算
            {
            case '+':
                current_value += atof(current_input); // 加法
                break;
            case '-':
                current_value -= atof(current_input); // 减法
                break;
            case 'X':
                current_value *= atof(current_input); // 乘法
                break;
            case '/':
                if (atof(current_input) != 0)
                {
                    current_value /= atof(current_input); // 除法
                }
                else
                {
                    lv_textarea_set_text(display, "Error");
                    return;
                }
                break;
            }
            last_operator = 0;       // 清除上一个操作符
            current_input[0] = '\0'; // 清空当前输入
            char buf[32];
            snprintf(buf, sizeof(buf), "%.6g", current_value); // 格式化当前值
            lv_textarea_set_text(display, buf);                // 更新显示区域
        }
    }
}

void ui_test()
{
    // 网格定义
    static int16_t main_col_dsc[] = {800, LV_GRID_TEMPLATE_LAST};     // 主容器列描述
    static int16_t main_row_dsc[] = {80, 400, LV_GRID_TEMPLATE_LAST}; // 主容器行描述

    static int16_t button_col_dsc[] = {188, 188, 188, 188, LV_GRID_TEMPLATE_LAST}; // 按钮区域列描述
    static int16_t button_row_dsc[] = {88, 88, 88, 88, LV_GRID_TEMPLATE_LAST};     // 按钮区域行描述

    /* 创建主容器 */
    lv_obj_t *cont = lv_obj_create(lv_scr_act());
    lv_obj_set_size(cont, 800, 480);
    lv_obj_set_style_pad_all(cont, 0, 0);

    lv_obj_center(cont); // 居中容器

    /* 设置主容器为网格布局 */
    lv_obj_set_layout(cont, LV_LAYOUT_GRID);
    lv_obj_set_style_grid_column_dsc_array(cont, main_col_dsc, 0);
    lv_obj_set_style_grid_row_dsc_array(cont, main_row_dsc, 0);
    lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE); // 禁用滚动条

    /* 创建文本框 - 放在网格第0行 */
    display = lv_textarea_create(cont);
    lv_obj_set_size(display, 700, 80);
    lv_obj_set_style_pad_all(display, 0, 0);
    lv_obj_set_style_text_font(display, &lv_font_montserrat_48, 0);
    lv_obj_set_grid_cell(display,
                         LV_GRID_ALIGN_STRETCH, 0, 1,  // 跨1列
                         LV_GRID_ALIGN_STRETCH, 0, 1); // 占1行
    lv_obj_set_style_bg_color(display, lv_color_hex(0xffffff), LV_PART_MAIN);
    lv_textarea_set_one_line(display, true);
    lv_textarea_set_placeholder_text(display, "0");

    /* 创建按钮区域 - 放在网格第1行 */
    lv_obj_t *inputarea = lv_obj_create(cont);
    lv_obj_set_layout(inputarea, LV_LAYOUT_GRID);
    lv_obj_set_style_pad_all(inputarea, 0, 0);

    lv_obj_set_size(inputarea, 800, 400);
    lv_obj_set_grid_cell(inputarea,
                         LV_GRID_ALIGN_STRETCH, 0, 1,  // 跨1列
                         LV_GRID_ALIGN_STRETCH, 1, 1); // 占1行
    lv_obj_set_style_grid_column_dsc_array(inputarea, button_col_dsc, 0);
    lv_obj_set_style_grid_row_dsc_array(inputarea, button_row_dsc, 0);

    lv_obj_t *label;
    lv_obj_t *btn;
    const char *btn_map[] = {"7", "8", "9", "X",
                             "4", "5", "6", "-",
                             "1", "2", "3", "+",
                             "/", "0", ".", "="};
    uint32_t i;
    for (i = 0; i < 16; i++)
    {
        uint8_t col = i % 4;
        uint8_t row = i / 4;

        btn = lv_btn_create(inputarea);
        /* Stretch the cell horizontally and vertically too
         * Set span to 1 to make the cell 1 column/row sized*/
        lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_STRETCH, col, 1,
                             LV_GRID_ALIGN_STRETCH, row, 1);
        // 设置按钮颜色
        if (strchr("X/-+=.", btn_map[i][0])) // 如果是特殊操作符
        {
            lv_obj_set_style_bg_color(btn, lv_color_hex(0xF0A000), LV_PART_MAIN); // 设置背景颜色
        }
        else // 如果是普通数字
        {
            lv_obj_set_style_bg_color(btn, lv_color_hex(0x123456), LV_PART_MAIN); // 设置背景颜色
        }

        label = lv_label_create(btn);
        lv_obj_set_style_text_font(label, &lv_font_montserrat_48, 0);
        lv_label_set_text(label, btn_map[i]); // 设置标签文本
        lv_obj_center(label);

        // 添加按钮点击事件回调
        lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, display);
    }
}

int main(void)
{
    /*LittlevGL init*/
    lv_init();
    // 初始化输入输出
    init_input_output();

    // 界面测试
    ui_test();

    // create_calculator(lv_scr_act());
    while (1)
    {
        lv_timer_handler();
        usleep(5000);
    }
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if (start_ms == 0)
    {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }
    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}
